package com.ruoyi.site.service.impl;

import com.ruoyi.site.controller.StripeWebhookController;
import com.ruoyi.site.domain.OrderDetails;
import com.ruoyi.site.service.IOrderDetailsService;
import com.ruoyi.site.service.IStripeService;
import com.stripe.StripeClient; // 导入 StripeClient
import com.stripe.model.Event;
import com.stripe.model.PaymentIntent;
import com.stripe.net.Webhook;
import com.stripe.param.PaymentIntentCreateParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.domain.AjaxResult;
import com.stripe.exception.StripeException; // 导入异常

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;

@Service
public class StripeServiceImpl implements IStripeService {

    @Value("${stripe.api.key}")
    private String stripeApiKey;

    @Value("${stripe.webhook.secret}")
    private String webhookSecret;

    @Autowired
    private IOrderDetailsService orderDetailsService;

    // 声明 StripeClient 实例
    private StripeClient stripeClient;
    private static final Logger log = LoggerFactory.getLogger(StripeServiceImpl.class);

    /**
     * 初始化：创建 StripeClient 实例
     */
    @PostConstruct
    public void init() {
        // 使用配置的 API Key 初始化 StripeClient
        this.stripeClient = new StripeClient(stripeApiKey);
    }

    @Override
    public AjaxResult createPaymentIntent(OrderDetails order) {
        // Stripe 金额单位是“分”
        long amountInCents = order.getTotalAmount().multiply(new BigDecimal(100)).longValue();

        try {
            PaymentIntentCreateParams params = PaymentIntentCreateParams.builder()
                    .setAmount(amountInCents)
                    .setCurrency(order.getCurrency())
                    .putMetadata("orderId", order.getOrderId().toString())
                    .setAutomaticPaymentMethods(
                            PaymentIntentCreateParams.AutomaticPaymentMethods.builder()
                                    .setEnabled(true) // 启用自动支付方法
                                    .build()
                    )
                    .build();

            // client.v1().paymentIntents().create(params);
            PaymentIntent paymentIntent = stripeClient.paymentIntents().create(params);

            // 将 Payment Intent ID 保存回订单
            order.setPaymentIntentId(paymentIntent.getId());
            orderDetailsService.updateOrderDetails(order);

            // 返回 client_secret 给前端
            Map<String, String> responseData = new HashMap<>();
            responseData.put("clientSecret", paymentIntent.getClientSecret());

            return AjaxResult.success(responseData);

        } catch (StripeException e) { // 捕获 Stripe 特定的异常
            return AjaxResult.error("创建支付失败: " + e.getMessage());
        } catch (Exception e) {
            // 捕获其他运行时异常
            return AjaxResult.error("创建支付失败（系统错误）: " + e.getMessage());
        }
    }
    @Override
    public void handleWebhook(byte[] payload, String stripeSignature) {

        String payloadString;
        try {
            payloadString = new String(payload, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("【Stripe Webhook】Payload 无法解析为 UTF-8 字符串", e);
            throw new RuntimeException("Payload encoding error", e);
        }

        log.info("【Stripe Webhook DEBUG】接收到的 Payload (from bytes): {}", payloadString);
        log.info("【Stripe Webhook DEBUG】接收到的 Signature: {}", stripeSignature);
        log.info("【Stripe Webhook DEBUG】使用的 Webhook Secret: {}", webhookSecret);

        try {
            log.info("【Stripe Webhook】开始验证和解析事件...");
            Event event = Webhook.constructEvent(payloadString, stripeSignature, webhookSecret);

            String eventType = event.getType();
            log.info("【Stripe Webhook】事件类型: {}", eventType);

            // --- 处理支付成功事件 ---
            if ("payment_intent.succeeded".equals(eventType)) {
                PaymentIntent paymentIntent = event.getDataObjectDeserializer()
                        .getObject()
                        .filter(obj -> obj instanceof PaymentIntent) // 确保是 PaymentIntent 类型
                        .map(obj -> (PaymentIntent) obj) // 安全转换
                        .orElse(null); // 如果失败，则返回 null，而不是抛出异常

                if (paymentIntent == null) {
                    log.error("【支付成功】事件解析成功，但未能提取 PaymentIntent 对象或类型不匹配。");
                    return;
                }

                log.info("【支付成功】PaymentIntent ID: {}", paymentIntent.getId());

                // 从元数据中获取我们的订单ID
                String orderIdStr = paymentIntent.getMetadata().get("orderId");
                log.info("【支付成功】关联订单ID: {}", orderIdStr);

                if (orderIdStr == null) {
                    log.error("【支付成功】元数据中缺少 orderId，无法处理。");
                    return; // 结束处理
                }

                OrderDetails order = orderDetailsService.selectOrderDetailsByOrderId(Long.parseLong(orderIdStr));

                if (order == null) {
                    log.warn("【支付成功】订单 {} 未找到，可能已在其他地方处理或订单ID错误。", orderIdStr);
                } else if (!"PENDING_PAYMENT".equals(order.getStatus())) {
                    log.warn("【支付成功】订单 {} 状态不是 PENDING_PAYMENT (当前状态: {})，忽略重复通知。", orderIdStr, order.getStatus());
                } else {
                    // 1. 更新订单状态为已支付
                    order.setStatus("PAID");
                    orderDetailsService.updateOrderDetails(order);
                    log.info("【支付成功】订单 {} 状态更新为 PAID。", order.getOrderId());

                    // 2. 执行“发货”逻辑：授权用户下载
                    orderDetailsService.grantLicensesForOrder(order.getOrderId()); // 调用授权方法
                    log.info("【支付成功】订单 {} 授权（发货）逻辑执行成功。", order.getOrderId());
                }

                // --- 处理支付失败事件 ---
            } else if ("payment_intent.payment_failed".equals(eventType)) {
                PaymentIntent paymentIntent = (PaymentIntent) event.getDataObjectDeserializer().getObject().get();
                log.warn("【支付失败】PaymentIntent ID: {}", paymentIntent.getId());

                String orderIdStr = paymentIntent.getMetadata().get("orderId");
                log.warn("【支付失败】关联订单ID: {}", orderIdStr);

                // 确保 orderId 存在
                if (orderIdStr != null) {
                    OrderDetails order = orderDetailsService.selectOrderDetailsByOrderId(Long.parseLong(orderIdStr));

                    if (order != null && "PENDING_PAYMENT".equals(order.getStatus())) {
                        // 支付失败，更新订单状态
                        order.setStatus("FAILED");
                        // 记录失败原因 (获取 Stripe 的错误信息)
                        String errorMsg = paymentIntent.getLastPaymentError() != null ?
                                paymentIntent.getLastPaymentError().getMessage() : "未知支付错误";

                        // order.setPaymentErrorMessage(errorMsg); // 如果 OrderDetails 有这个字段
                        orderDetailsService.updateOrderDetails(order);
                        log.error("【支付失败】订单 {} 状态更新为 FAILED。原因: {}", order.getOrderId(), errorMsg);
                    } else if (order != null) {
                        log.warn("【支付失败】订单 {} 状态非 PENDING_PAYMENT (当前状态: {})，忽略。", orderIdStr, order.getStatus());
                    } else {
                        log.error("【支付失败】订单 {} 未找到，无法更新状态。", orderIdStr);
                    }
                }
            } else {
                // 处理其他事件，例如 charge.refunded, checkout.session.completed 等
                log.info("【Stripe Webhook】收到未处理的事件类型: {}", eventType);
            }

        } catch (Exception e) {
            // 捕获签名验证失败、JSON 解析失败、或强制转换失败等所有底层错误
            log.error("【Stripe Webhook】处理过程中发生严重异常！", e);
            // 确保异常被重新抛出，以便 Controller 返回 400，Stripe 会重试。
            throw new RuntimeException("Stripe Webhook 处理失败", e);
        }
    }
}